package com.yehui.sentinel.window;

import com.alibaba.csp.sentinel.slots.statistic.base.LeapArray;
import com.alibaba.csp.sentinel.slots.statistic.base.WindowWrap;

import java.util.concurrent.atomic.LongAdder;

/**
 * @author 业徽
 * @date 2021/7/20
 */
public class LeapArrayDemo {

    static class SlowRequestCounter {
        private LongAdder slowCount;
        private LongAdder totalCount;

        public SlowRequestCounter() {
            this.slowCount = new LongAdder();
            this.totalCount = new LongAdder();
        }

        public LongAdder getSlowCount() {
            return slowCount;
        }

        public LongAdder getTotalCount() {
            return totalCount;
        }

        public SlowRequestCounter reset() {
            slowCount.reset();
            totalCount.reset();
            return this;
        }

        @Override
        public String toString() {
            return "SlowRequestCounter{" +
                    "slowCount=" + slowCount +
                    ", totalCount=" + totalCount +
                    '}';
        }
    }

    static class SlowRequestLeapArray extends LeapArray<SlowRequestCounter> {

        public SlowRequestLeapArray(int sampleCount, int intervalInMs) {
            super(sampleCount, intervalInMs);
        }

        @Override
        public SlowRequestCounter newEmptyBucket(long timeMillis) {
            return new SlowRequestCounter();
        }

        @Override
        protected WindowWrap<SlowRequestCounter> resetWindowTo(WindowWrap<SlowRequestCounter> w, long startTime) {
            w.resetTo(startTime);
            w.value().reset();
            return w;
        }
    }

    public static void main(String[] args) throws InterruptedException {
        // 1秒
        final SlowRequestLeapArray slowRequestLeapArray = new SlowRequestLeapArray(1, 1000);
        slowRequestLeapArray.currentWindow().value().totalCount.add(1);

        Thread.sleep(500);
        slowRequestLeapArray.currentWindow().value().totalCount.add(1);

        // 这个是 2
        System.out.println("count: " + slowRequestLeapArray.currentWindow().value().totalCount.intValue());

        Thread.sleep(500);

        // 这个是 0
        System.out.println("count: " + slowRequestLeapArray.currentWindow().value().totalCount.intValue());

        // 他统计的是固定 1 秒，而不是连续的 1 秒
        // 假如起始时间是 0, 那么在 355ms 看的数据是落在 0-1s 这个 bucket 的数据，
        // 在 2355 ms 看的数据是落在 2-3s 这个 bucket 的数据，而不是 1355ms - 2355ms 之间的数据
        // 因为 sentinel 的滑动窗口是用了统计数据的，这样就行了
    }

}
